#ifndef _TDESEncryptCallBacker_H_
#define _TDESEncryptCallBacker_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <openssl/des.h>
#include "../Utils/ConvertUtil.h"
using namespace std;
#define LEN_OF_KEY 24

#define ENCRYPT 1
#define DECRYPT 0
class TDESEncryptCallBacker:public EncryptCallBacker{
private:
	string model(const string &source,const string &_k,bool mode);
public:
	string encrypt(const string& strSrc,const string &key) override;
	string decrypt(const string& strSrc,const string &key,int len)override;
};
string  TDESEncryptCallBacker::model(const string &source,const string &_k,bool mode)
{
	int docontinue = 1;
	char *data=(char *)source.c_str();
	int data_len;
        	int data_rest;
        	unsigned char ch;
        	unsigned char *src = NULL; /* 补齐后的明文 */
        	unsigned char *dst = NULL; /* 解密后的明文 */
        	int len;
        	unsigned char tmp[8];
        	unsigned char in[8];
        	unsigned char out[8];
        	char *k = (char *)_k.c_str(); /* 原始密钥 */
        	int key_len;
        	unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */
        	unsigned char block_key[9];
        	DES_key_schedule ks,ks2,ks3;
        	key_len = strlen(k);
        	memcpy(key, k, key_len);
        	memset(key + key_len, 0x00, LEN_OF_KEY - key_len);
        	data_len = strlen(data);
        	data_rest = data_len % 8;
       	len = data_len + (8 - data_rest);
        	ch = 8 - data_rest;
        	src = (unsigned char *)malloc(len);
        	dst = (unsigned char *)malloc(len);
        	if (NULL == src || NULL == dst)
        	{
            		docontinue = 0;
        	}
        	if (docontinue)
        	{
        		int count;
            		int i;
            		/* 构造补齐后的加密内容 */
            		memset(src, 0, len);
            		memcpy(src, data, data_len);
            		memset(src + data_len, ch, 8 - data_rest);
            		/* 密钥置换 */
            		memset(block_key, 0, sizeof(block_key));
            		memcpy(block_key, key + 0, 8);
            		DES_set_key_unchecked((const_DES_cblock*)block_key, &ks);
            		memcpy(block_key, key + 8, 8);
            		DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2);
            		memcpy(block_key, key + 16, 8);
            		DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3);
            		/* 循环加密，每8字节一次 */
            		count = len / 8;
            		for (i = 0; i < count; i++)
            		{
                		memset(tmp, 0, 8);
                		memset(in, 0, 8);
                		memset(out, 0, 8);
                		memcpy(tmp, src + 8 * i, 8);
               		 /* 加密 */
                		if(mode)
                			DES_ecb3_encrypt((const_DES_cblock*)tmp, (DES_cblock*)in, &ks, &ks2, &ks3, DES_ENCRYPT);
                		else
                			DES_ecb3_encrypt((const_DES_cblock*)tmp, (DES_cblock*)in, &ks, &ks2, &ks3, DES_DECRYPT);
                		memcpy(dst + 8 * i, in, 8);
        		}
        	}

        	string result=ConvertUtil::uc_to_string(dst,len);
        	
        	
        	if (NULL != src)
       	{
             		free(src);
              	src = NULL;
              }
              if (NULL != dst)
              {
              	free(dst);
              	dst = NULL;
              } 
             return  result;
}

string TDESEncryptCallBacker::encrypt(const string& strSrc,const string &key)
{
	string result=model(strSrc,key,ENCRYPT);
	return result;
}
string TDESEncryptCallBacker::decrypt(const string& strSrc,const string &key,int len)
{
	string result=model(strSrc,key,DECRYPT);
	return result.substr(0,len);
}
#endif 